/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = postgresql_comm.c                                             */
/*  NOTE      = postgresql共通                                                 */
/*  DATE      = 2016/01/06 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include <limits.h>

#include "postgresql_core.h"
#include "postgresql_comm.h"

#define POSTGRESQL_REPORT_KEY_DBNAME     APM_REPORT_KEY_SESSION".postgresql.dbname"

/* 格式5位是error code字符串+space+对应自定义code */
/* 非数字的从10000开始 */
char arr_err_code[][12] =
{
    "08000 8000",
    "08003 8003",
    "08006 8006",
    "08001 8001",
    "08004 8004",
    "08007 8007",
    "08P01 10000",
    "09000 9000",
    "0A000 10001",
    "0B000 10002",
    "0F000 10003",
    "0F001 10004",
    "0L000 10005",
    "0LP01 10006",
    "0P000 10007",
    "0Z000 10008",
    "0Z002 10009",
    "20000 20000",
    "21000 21000",
    "22000 22000",
    "2202E 10010",
    "22021 22021",
    "22008 22008",
    "22012 22012",
    "22005 22005",
    "2200B 10011",
    "22022 22022",
    "22015 22015",
    "2201E 10012",
    "22014 22014",
    "22016 22016",
    "2201F 10013",
    "2201G 10014",
    "22018 22018",
    "22007 22007",
    "22019 22019",
    "2200D 10015",
    "22025 22025",
    "22P06 10016",
    "22010 22010",
    "22023 22023",
    "2201B 10017",
    "2201W 10018",
    "2201X 10019",
    "2202H 10020",
    "2202G 10021",
    "22009 22009",
    "2200C 10022",
    "2200G 10023",
    "22004 22004",
    "22002 22002",
    "22003 22003",
    "22026 22026",
    "22001 22001",
    "22011 22011",
    "22027 22027",
    "22024 22024",
    "2200F 10024",
    "22P01 10025",
    "22P02 10026",
    "22P03 10027",
    "22P04 10028",
    "22P05 10029",
    "2200L 10030",
    "2200M 10031",
    "2200N 10032",
    "2200S 10033",
    "2200T 10034",
    "23000 23000",
    "23001 23001",
    "23502 23502",
    "23503 23503",
    "23505 23505",
    "23514 23514",
    "23P01 10035",
    "24000 24000",
    "25000 25000",
    "25001 25001",
    "25002 25002",
    "25008 25008",
    "25003 25003",
    "25004 25004",
    "25005 25005",
    "25006 25006",
    "25007 25007",
    "25P01 10036",
    "25P02 10037",
    "26000 26000",
    "27000 27000",
    "28000 28000",
    "28P01 10038",
    "2B000 10039",
    "2BP01 10040",
    "2D000 10041",
    "2F000 10042",
    "2F005 10043",
    "2F002 10044",
    "2F003 10045",
    "2F004 10046",
    "34000 34000",
    "38000 38000",
    "38001 38001",
    "38002 38002",
    "38003 38003",
    "38004 38004",
    "39000 39000",
    "39001 39001",
    "39004 39004",
    "39P01 10047",
    "39P02 10048",
    "39P03 10049",
    "3B000 10050",
    "3B001 10051",
    "3D000 10052",
    "3F000 10053",
    "40000 40000",
    "40002 40002",
    "40001 40001",
    "40003 40003",
    "40P01 10054",
    "42000 42000",
    "42601 42601",
    "42501 42501",
    "42846 42846",
    "42803 42803",
    "42P20 10055",
    "42P19 10056",
    "42830 42830",
    "42602 42602",
    "42622 42622",
    "42939 42939",
    "42804 42804",
    "42P18 10057",
    "42P21 10058",
    "42P22 10059",
    "42809 42809",
    "42703 42703",
    "42883 42883",
    "42P01 10060",
    "42P02 10061",
    "42704 42704",
    "42701 42701",
    "42P03 10062",
    "42P04 10063",
    "42723 42723",
    "42P05 10064",
    "42P06 10065",
    "42P07 10066",
    "42712 42712",
    "42710 42710",
    "42702 42702",
    "42725 42725",
    "42P08 10067",
    "42P09 10068",
    "42P10 10069",
    "42611 42611",
    "42P11 10070",
    "42P12 10071",
    "42P13 10072",
    "42P14 10073",
    "42P15 10074",
    "42P16 10075",
    "42P17 10076",
    "44000 44000",
    "53000 53000",
    "53100 53100",
    "53200 53200",
    "53300 53300",
    "53400 53400",
    "54000 54000",
    "54001 54001",
    "54011 54011",
    "54023 54023",
    "55000 55000",
    "55006 55006",
    "55P02 10077",
    "55P03 10078",
    "57000 57000",
    "57014 57014",
    "57P01 10079",
    "57P02 10080",
    "57P03 10081",
    "57P04 10082",
    "58000 58000",
    "58030 58030",
    "58P01 10083",
    "58P02 10084",
    "F0000 10085",
    "F0001 10086",
    "HV000 10087",
    "HV005 10088",
    "HV002 10089",
    "HV010 10090",
    "HV021 10091",
    "HV024 10092",
    "HV007 10093",
    "HV008 10094",
    "HV004 10095",
    "HV006 10096",
    "HV091 10097",
    "HV00B 10098",
    "HV00C 10099",
    "HV00D 10100",
    "HV090 10101",
    "HV00A 10102",
    "HV009 10103",
    "HV014 10104",
    "HV001 10105",
    "HV00P 10106",
    "HV00J 10107",
    "HV00K 10108",
    "HV00Q 10109",
    "HV00R 10110",
    "HV00L 10111",
    "HV00M 10112",
    "HV00N 10113",
    "P0000 10114",
    "P0001 10115",
    "P0002 10116",
    "P0003 10117",
    "P0004 10118",
    "XX000 10119",
    "XX001 10120",
    "XX002 10121"
};

/*******************************************************************************
*  FUNC     :  调试用
*  ARGS     :  void
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_dbg(void)
{
    return;
}

/*******************************************************************************
*  FUNC     :  字符串转数字
*  ARGS     :  p_inbuff (入力字符串)
*           :  p_ui_len (转换后的数字)
*  RTN      :  FR_FAIL      (FAIL)
*              FR_SUCC      (SUCC)
*  NOTE     :
*******************************************************************************/
int postgresql_atol(char *p_inbuff, unsigned long *p_ul_len)
{
    int i_tmp = 0;
    unsigned long ul_len = 0;

    /* 装换成数值 */
    while (*p_inbuff)
    {
        i_tmp = *p_inbuff - '0';
        if (i_tmp > 9 || i_tmp < 0)
        {
            return FR_FAIL;
        }
        ul_len = ul_len * 10 + i_tmp;
        p_inbuff++;
    }

    *p_ul_len = ul_len;
    return FR_SUCC;
}


/*******************************************************************************
*  FUNC     :  快速排列
*  ARGS     :  i_start (开始位置)
*           :  i_right (结束位置)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_quicksort(int i_start, int i_right)
{
    if (i_right == -1)
    {
        i_right = sizeof(arr_err_code)/12 - 1;
    }
    int i_min = i_start;
    int i_max = i_right;
    int i_left = i_start;
    char arr_tmp[12] = {0};
    strcpy(arr_tmp, arr_err_code[i_start]);

    while(i_min < i_max)
    {
        while(strncmp(arr_err_code[i_max], arr_tmp, 5) >= 0 && i_max >= i_left)
        {
            i_max--;
        }
        if(i_max > i_left)
        {
            strcpy(arr_err_code[i_left], arr_err_code[i_max]);
            i_left=i_max;
        }
        while(strncmp(arr_err_code[i_min], arr_tmp, 5) <= 0 && i_min <= i_left)
        {
            i_min++;
        }
        if(i_min < i_left)
        {
            strcpy(arr_err_code[i_left], arr_err_code[i_min]);
            i_left = i_min;
        }
    }

    strcpy(arr_err_code[i_left], arr_tmp);
    if(i_left - i_start > 1)
    {
        postgresql_quicksort(i_start, i_left - 1);
    }
    if(i_right - i_left > 1)
    {
        postgresql_quicksort(i_left + 1, i_right);
    }
    return;
}


/*******************************************************************************
*  FUNC     :  取得对应error code
*  ARGS     :  i_start (开始位置)
*           :  i_right (结束位置)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
int postgresql_err_code(char *p_err_code)
{
    int i_low = 0;
    int i_high = sizeof(arr_err_code)/12 - 1;
    int i_mid = 0;
    char *p_acl = NULL;
    int i_code = 0;

	while (i_low < i_high)
    {
		i_mid = (i_low + i_high) / 2;

		if (strncmp(arr_err_code[i_mid], p_err_code, 5) == 0)
		{
            p_acl = arr_err_code[i_mid];
            break;
		}
		else if (strncmp(arr_err_code[i_mid], p_err_code, 5) > 0)
		{
            i_high = i_mid;
		}
		else
		{
		    i_low = i_mid + 1;
		}
	}

	if (p_acl == NULL)
    {
        return 99999;
    }
    else
    {
        p_acl += 6;
        i_code = atoi(p_acl);
        return i_code;
    }
}

/*******************************************************************************
*  FUNC     :  跳过指定长度
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  i_len(指定长度)
*           :  p_i_len(当前packet剩余长度)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int postgresql_skip_len(Frbyte_Packet *p_st_data
                        , int i_len
                        , int *p_i_len)
{
    int i_ret = FR_SUCC;

    if (*p_i_len < i_len)
    {
        return FR_FAIL;
    }
    i_ret = bytebuff_skip(p_st_data, i_len);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    *p_i_len -= i_len;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得short
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  p_i_len(当前packet剩余长度)
*           :  p_i_value(出力值)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int postgresql_get_short(Frbyte_Packet *p_st_data
                        , int *p_i_len
                        , int *p_i_value)
{
    int i_ret = FR_SUCC;
    uint16_t u16_value = 0;
    short s_value = 0;

    if (*p_i_len < 2)
    {
        return FR_FAIL;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }
    s_value = (short)u16_value;

    *p_i_value = s_value;
    *p_i_len -= 2;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得int
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  p_i_len(当前packet剩余长度)
*           :  p_i_value(出力值)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int postgresql_get_int(Frbyte_Packet *p_st_data
                      , int *p_i_len
                      , int *p_i_value)
{
    int i_ret = FR_SUCC;
    uint32_t u32_value = 0;
    int i_value = 0;

    if (*p_i_len < 4)
    {
        return FR_FAIL;
    }
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }
    i_value = (int)u32_value;

    *p_i_value = i_value;
    *p_i_len -= 4;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得int
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  p_i_value(出力值)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int postgresql_get_int2(Frbyte_Packet *p_st_data, int *p_i_value)
{
    int i_ret = FR_SUCC;
    uint32_t u32_value = 0;
    int i_value = 0;

    i_ret = bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }
    i_value = (int)u32_value;

    *p_i_value = i_value;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过string
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  p_i_len(当前packet剩余长度)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int postgresql_skip_string(Frbyte_Packet *p_st_data
                           , int *p_i_len)
{
    int i_ret = FR_SUCC;
    const char *p_end_str = "\0";
    int i_end_len = 1;
    int i_len = *p_i_len;
    int i_index = 0;

    if (i_len <= 0)
    {
        return FR_FAIL;
    }

    /* 找到字符串结尾[\0] */
    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                           , bytebuff_getPosition(p_st_data) + i_len
                           , p_end_str, i_end_len, &i_index);
    if (i_ret != FR_SUCC || i_index < bytebuff_getPosition(p_st_data))
    {
        return FR_FAIL;
    }

    i_index -= bytebuff_getPosition(p_st_data);
    /* skip */
    i_ret = bytebuff_skip(p_st_data, i_index + i_end_len);
    if (i_ret != FR_SUCC)
    {
        return FR_FAIL;
    }

    *p_i_len -= i_index + i_end_len;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得string
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  p_i_len(当前packet剩余长度)
*           :  pp_out_str(出力字符串)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int postgresql_get_string(Frbyte_Packet *p_st_data
                         , int *p_i_len
                         , char **pp_out_str)
{
    int i_ret = FR_SUCC;
    const char *p_end_str = "\x00";
    int i_end_len = 1;
    int i_len = *p_i_len;
    int i_index = 0;
    char *p_str = NULL;

    if (i_len <= 0)
    {
        return FR_FAIL;
    }

    /* 找到字符串结尾[\0] */
    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                           , bytebuff_getPosition(p_st_data) + i_len
                           , p_end_str, i_end_len, &i_index);
    if (i_ret != FR_SUCC || i_index < bytebuff_getPosition(p_st_data))
    {
        return FR_FAIL;
    }
    i_index -= bytebuff_getPosition(p_st_data);

    /* 无值(以[\0]结尾) */
    if (i_index == 0)
    {
        bytebuff_skip(p_st_data, i_end_len);
        *p_i_len -= 1;
        *pp_out_str = NULL;
        return FR_SUCC;
    }

    /* 取得字符串 */
    p_str = (char *)frmalloc(i_index + 1);
    if (p_str == NULL)
    {
        return FR_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_str, i_index);
    if (i_ret != FR_SUCC)
    {
        frfree(p_str);
        return FR_FAIL;
    }

    p_str[i_index] = '\0';
    bytebuff_skip(p_st_data, i_end_len);
    *p_i_len -= i_index + 1;
    *pp_out_str = p_str;
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得bind参数
*  ARGS     :  p_st_data(bytebuff数据包)
*           :  p_i_len(当前packet剩余长度)
*           :  i_data_len(当前数据长度)
*           :  c_data_type(当前数据类型)
*           :  p_lst_bind(参数列表)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :  p_lst_bind必须不为NULL
*******************************************************************************/
int psotgresql_get_bind(Frbyte_Packet *p_st_data
                        , int *p_i_len
                        , int i_data_len
                        , char c_data_type
                        , Sql_field_bind *p_lst_bind)
{
    int i_ret = FR_SUCC;
    Frdata_field *p_st_value = NULL;
    char *p_data  = NULL;
    Frlist_node *p_st_node = NULL;

    if (i_data_len < -1)
    {
        frdbg("Please attention!\n");
        return FR_FAIL;
    }
    /* 创建Frdata_field */
    p_st_value = (Frdata_field *)frmalloc(sizeof(Frdata_field));
    if (p_st_value == NULL)
    {
        return FR_FAIL;
    }
    memset(p_st_value, 0x0, sizeof(Frdata_field));

    /* 有值 */
    if (i_data_len > 0)
    {
        /* 长度不匹配 */
        if (*p_i_len < i_data_len)
        {
            frfree(p_st_value);
            return FR_FAIL;
        }
        /* text类型 */
        if (c_data_type == POSTGRESQL_TEXT)
        {
            p_data = (char *)frmalloc(i_data_len + 1);
            if (p_data == NULL)
            {
                frfree(p_st_value);
                return FR_FAIL;
            }
            i_ret = bytebuff_get_bytes(p_st_data, p_data, i_data_len);
            if (i_ret != FR_SUCC)
            {
                frfree(p_data);
                frfree(p_st_value);
                return FR_FAIL;
            }
            p_data[i_data_len] = '\0';
        }
        /* binary类型 */
        else
        {
            i_ret = bytebuff_skip(p_st_data, i_data_len);
            if (i_ret != FR_SUCC)
            {
                frfree(p_st_value);
                return FR_FAIL;
            }
            p_data = frstrdup("BINARY");
        }
        p_st_value->p_field_value = p_data;
        *p_i_len -= i_data_len;
    }

    /* 追加到bind list中 */
    p_st_node = frlist_node_create(p_st_value);
    if (p_st_node == NULL)
    {
        frtds_free_param(&p_st_value);
        return FR_FAIL;
    }

    frlist_push(&p_lst_bind->st_field_list, p_st_node);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  销毁command
*  ARGS     :  pp_st_command(command信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_free_cmd(Postgresql_req_cmd **pp_st_command)
{
    if (pp_st_command == NULL || *pp_st_command == NULL)
    {
        return;
    }

    Postgresql_req_cmd *p_st_command = *pp_st_command;
    if (p_st_command->p_err_msg)
    {
        frfree(p_st_command->p_err_msg);
    }
    if (p_st_command->p_cursor_str)
    {
        frfree(p_st_command->p_cursor_str);
    }
    if (p_st_command->i_new_flg == FR_YES)
    {
        frdb_statement_free(&p_st_command->p_st_statement);
    }
    frdb_resultset_free(&p_st_command->p_st_resultset);
    frfree(p_st_command);

    *pp_st_command = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  销毁command node
*  ARGS     :  p_st_node(command node)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_cmd_node_free(Frlist_node *p_st_node)
{
    if (p_st_node == NULL || p_st_node->data == NULL)
    {
        return;
    }

    Postgresql_req_cmd *p_st_command = (Postgresql_req_cmd *)p_st_node->data;
    if (p_st_command->p_err_msg)
    {
        frfree(p_st_command->p_err_msg);
    }
    if (p_st_command->p_cursor_str)
    {
        frfree(p_st_command->p_cursor_str);
    }
    if (p_st_command->i_new_flg == FR_YES)
    {
        frdb_statement_free(&p_st_command->p_st_statement);
    }
    frdb_resultset_free(&p_st_command->p_st_resultset);
    frfree(p_st_node->data);

    return;
}

/*******************************************************************************
*  FUNC     :  初始化fragment
*  ARGS     :  p_st_fragment(分片包数据)
*           :  i_need_req_resp(方向:FR_CLIENT_IP_PORT/FR_SRV_IP_PORT)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_init_fragment(L7_fragment_postgresql *p_st_fragment
                              , int i_need_req_resp)
{
    if (p_st_fragment == NULL)
    {
        return;
    }

    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    memset(p_st_fragment, 0x0, sizeof(L7_fragment_postgresql));
    p_st_fragment->i_need_req_resp = i_need_req_resp;

    return;
}

/*******************************************************************************
*  FUNC     :  销毁fragment
*  ARGS     :  pp_st_fragment(分片包数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_destroy_fragment(L7_fragment_postgresql **pp_st_fragment)
{
    if (pp_st_fragment == NULL || *pp_st_fragment == NULL)
    {
        return;
    }

    L7_fragment_postgresql *p_st_fragment = *pp_st_fragment;
    if (p_st_fragment->p_st_data)
    {
        bytebuff_free(&p_st_fragment->p_st_data);
    }
    frfree(p_st_fragment);
    *pp_st_fragment = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  销毁session
*  ARGS     :  pp_st_sess(session信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_destroy_session(L7session_postgresql **pp_st_sess)
{
    if(pp_st_sess == NULL || *pp_st_sess == NULL)
    {
        return;
    }

    L7session_postgresql *p_st_sess = *pp_st_sess;

    if (p_st_sess->p_db_name)
    {
        frfree(p_st_sess->p_db_name);
    }
    if (p_st_sess->p_db_user)
    {
        frfree(p_st_sess->p_db_user);
    }
    frfree(p_st_sess);
    *pp_st_sess = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  销毁request
*  ARGS     :  pp_st_req(request信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_destroy_request(L7_req_postgresql **pp_st_req)
{
    if(pp_st_req == NULL || *pp_st_req == NULL)
    {
        return;
    }

    L7_req_postgresql *p_st_req = *pp_st_req;
    frlist_remove_all(&p_st_req->st_command_lst, postgresql_cmd_node_free);

    frfree(p_st_req);
    *pp_st_req = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  销毁response
*  ARGS     :  pp_st_req(response信息)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void postgresql_destroy_response(L7_resp_postgresql **pp_st_resp)
{
    if(pp_st_resp == NULL || *pp_st_resp == NULL)
    {
        return;
    }

    L7_resp_postgresql *p_st_resp = *pp_st_resp;

    frfree(p_st_resp);
    *pp_st_resp = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  根据session创建session data列表
*  ARGS     :  p_st_conn (CT信息)
*           :  p_st_session (postgresql session信息)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_session必须不为NULL
*******************************************************************************/
Frreport_body_data* postgresql_new_report_body(Conntrack *p_st_conn
                                             , L7session_postgresql *p_st_sess)
{
    int i_ret = FR_SUCC;
    Frreport_body_data *p_st_sess_body = NULL;

    /* 创建report body */
    p_st_sess_body = frreport_body_new_l7(p_st_conn);
    if (p_st_sess_body == NULL)
    {
        return NULL;
    }
    /* 追加connection相关信息 */
    i_ret = frreport_body_l7_add_connInfo(p_st_sess_body, p_st_conn);
    if (i_ret != FR_SUCC)
    {
        frreport_body_free(&p_st_sess_body);
        return NULL;
    }

    /* add username */
    if (p_st_sess->p_db_user)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , APM_REPORT_KEY_SESSION_USERNAME
                                         , p_st_sess->p_db_user);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    /* add dbname */
    if (p_st_sess->p_db_name)
    {
        i_ret = frreport_body_l7_add_str(p_st_sess_body
                                         , POSTGRESQL_REPORT_KEY_DBNAME
                                         , p_st_sess->p_db_name);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }
    if (p_st_sess->st_login.tv_sec != 0
        || p_st_sess->st_login.tv_usec != 0)
    {
        /* add request start time */
        i_ret = frreport_body_l7_add_timeval(p_st_sess_body
                                            , APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP
                                            , &p_st_sess->st_login);
        if (i_ret != FR_SUCC)
        {
            frreport_body_free(&p_st_sess_body);
            return NULL;
        }
    }

    return p_st_sess_body;
}
